package com.sy.dept.config;

import io.swagger.annotations.ApiOperation;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.OAuthBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.oas.annotations.EnableOpenApi;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;

import javax.servlet.ServletContext;
import java.util.Collections;

/**
 * @author sy
 * @date 2022/1/5 11:30
 */
@Component//Spring扫描
@EnableOpenApi//开启OpenApi规范
@ConfigurationProperties("swagger")//配置前缀
@Data
public class SwaggerConfiguration {

    /**
     * 是否开启swagger，生产环境一般关闭，所以这里定义一个变量
     */
    private Boolean enable;

    /**
     * 项目应用名
     */
    private String applicationName;

    /**
     * 项目版本信息
     */
    private String applicationVersion;

    /**
     * 项目描述信息
     */
    private String applicationDescription;


//    @Bean
//    public Docket docket() {
//        return new Docket(DocumentationType.OAS_30)
//                .pathMapping("/")
//                // 定义是否开启swagger，false为关闭，可以通过变量控制，线上关闭
//                .enable(enable)
//                //配置api文档元信息
//                .apiInfo(apiInfo())
//                // 选择哪些接口作为swagger的doc发布
//                .select()
//                //apis() 控制哪些接口暴露给swagger，
//                // RequestHandlerSelectors.any() 所有都暴露
//                // RequestHandlerSelectors.basePackage("com.keep.*")  指定包位置
//                // withMethodAnnotation(ApiOperation.class)标记有这个注解 ApiOperation
//                .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
//
//                .paths(PathSelectors.any())
//
//                .build();
//    }
//
//    private ApiInfo apiInfo() {
//        return new ApiInfoBuilder()
//                .title(applicationName)
//                .description(applicationDescription)
//                .contact(new Contact("作者", "网站", "邮箱"))
//                .version(applicationVersion)
//                .build();
//    }

    @Autowired
    private ServletContext servletContext;

    /**
     * 添加摘要信息(Docket)
     */
    @Bean()
    public Docket apiConfig() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(this.apiInfo())// 调用apiInfo方法,创建一个ApiInfo实例,里面是展示在文档页面信息内容
                .select()
                // 加了ApiOperation注解的类，才生成接口文档
                .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
                // 指定路径类才能生成接口
//                .apis(RequestHandlerSelectors.basePackage("com.le.lcm.modules.am.controller"))
                .paths(PathSelectors.any())// 过滤的接口
                .build()
                .securityContexts(Collections.singletonList(securityContexts()))
                .securitySchemes(Collections.singletonList(securitySchemes()))
                .groupName("部门服务接口")
                // 关闭默认返回值
                .useDefaultResponseMessages(false);
    }


    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                // 大标题
                .title("部门接口文档")
                // 详细描述
                .description("描述：部门服务端")
                // 版本
                .version("版本号:1.0.0")
                // 作者
                .contact(new Contact("sunyu", "", "1870971964@qq.com"))
                // 许可证信息
//                .license("The Apache License, Version 2.0")
                // 许可证地址
//                .licenseUrl("http://www.apache.org/licenses/LICENSE-2.0.html")
                .build();
    }

    /**
     * 认证方式使用密码模式
     */
    private SecurityScheme securitySchemes() {
        GrantType grantType = new ResourceOwnerPasswordCredentialsGrant(servletContext.getContextPath() + "/oauth/token");

        return new OAuthBuilder()
                .name("Authorization")
                .grantTypes(Collections.singletonList(grantType))
                .scopes(Collections.<AuthorizationScope>emptyList())
                .build();
    }

    /**
     * 设置 swagger2 认证的安全上下文
     */
    private SecurityContext securityContexts() {
        return SecurityContext.builder()
                .securityReferences(Collections.singletonList(new SecurityReference("Authorization", scopes())))
                .forPaths(PathSelectors.any())
                .build();
    }

    /**
     * 允许认证的scope
     */
    private AuthorizationScope[] scopes() {
        AuthorizationScope authorizationScope = new AuthorizationScope("all", "接口测试");
        AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
        authorizationScopes[0] = authorizationScope;
        return authorizationScopes;
    }

}
